package com.gitee.srurl.core.util;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.gitee.srurl.core.api.IConfigCache;
import com.gitee.srurl.core.api.impl.cache.FileConfigCache;
import com.gitee.srurl.core.exception.ServiceException;
import com.gitee.srurl.core.properties.UniqueIdProperties;
import com.gitee.srurl.snow.domain.SnowflakeData;
import com.gitee.srurl.snow.domain.SnowflakeReportData;
import com.gitee.srurl.snow.gen.AbstractSnowflake;
import com.gitee.srurl.snow.gen.DefaultSnowflake;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * @author zxw
 * @date 2023/4/29 14:23
 */
@Slf4j
@Component
public class UniqueIdUtil {

    private static UniqueIdProperties uniqueIdProperties;

    private static AbstractSnowflake snowflake;

    private static volatile boolean initSuccess;

    @Autowired
    public void setUniqueIdProperties(UniqueIdProperties uniqueIdProperties) {
        UniqueIdUtil.uniqueIdProperties = uniqueIdProperties;
    }

    @PostConstruct
    private void init() {

        IConfigCache configCache = new FileConfigCache();
        // 默认项目读取这个只使用本地文件
        byte[] read = configCache.read(StrUtil.format("snowflake/snowflake_{}_{}.json",
                uniqueIdProperties.getWorkerId(), uniqueIdProperties.getDataCenterId()));

        if (ArrayUtil.isNotEmpty(read)) {
            SnowflakeReportData snowflakeReportDataTemp = JacksonUtil.parseObject(read, new TypeReference<>() {
            });
            // 上报数据的时间戳
            Long lastTimestamp = Optional.ofNullable(snowflakeReportDataTemp.getLastTimestamp()).orElse(-1L);
            // 说明发生了时钟回拨
            if (lastTimestamp > uniqueIdProperties.getLastTimestamp()) {
                // 后面会将当前时间设置为最新时间戳后面的1ms 因此不需要序列号
                uniqueIdProperties.setLastTimestamp(lastTimestamp);
            }
        }

        SnowflakeData snowflakeData = SnowflakeData.builder()
                .epoch(uniqueIdProperties.getEpoch())
                .workerId(uniqueIdProperties.getWorkerId())
                .dataCenterId(uniqueIdProperties.getDataCenterId())
                .timeOffset(uniqueIdProperties.getTimeOffset())
                .randomSequenceLimit(uniqueIdProperties.getRandomSequenceLimit())
                .backwardsHandle(uniqueIdProperties.getBackwardsHandle())
                .lastTimestamp(uniqueIdProperties.getLastTimestamp())
                .build();

        snowflake = new DefaultSnowflake(snowflakeData);
        initSuccess = true;
    }

    public static long nextId() {
        if (!initSuccess) {
            log.warn("id生成器未初始化完成");
            throw new ServiceException("id生成器未初始化完成！");
        }
        return snowflake.nextId();
    }
}
